/****************************************************************************
 * Copyright (c) 2017 - 2019 Qualcomm Technologies International, Ltd.
****************************************************************************/
/**
 * \file  opmgr_operator_data.h
 * \ingroup opmgr
 *
 * Private header defining the content of OPERATOR_DATA.
 *
 */

#ifndef OPMGR_OPERATOR_DATA_H
#define OPMGR_OPERATOR_DATA_H

#include "opmgr_common.h"
#ifdef PROFILER_ON
#include "platform/profiler_c.h"
#endif /* PROFILER_ON */
#include "sched_oxygen/sched_oxygen.h"
#include "adaptor/connection_id.h"
#include "rate/rate.h"
#include "buffer/buffer.h"
#include "stream/stream_common.h"


/* The implementation of suspend_processing for regular operators
 * can be one of the following:
 */
/* Wraps interrupt_block/unblock */
#define OPMGR_SYNC_KICKED_LEGACY    (1)
#define OPMGR_SYNC_KICKED_BASIC     (2)

/* The implementation of suspend_processing for strict timer driven operators
 * can be one of the following:
 */
/* Wraps interrupt_block/unblock */
#define OPMGR_SYNC_STRICT_TIMER_LEGACY  (1)


/** Operator states.
    This could be either be replaced by a boolean or extended to
    cover the functionality provided by processing_suspended and
    processing_rerun_requested.
 */
typedef enum
{
    OP_RUNNING,
    OP_NOT_RUNNING
} OP_STATE;

/** A structure for storing kick propagation data. This structure represents an
 * element in a list, stored as an array. */
typedef struct
{
    /** The touched terminal mask for this element */
    unsigned t_mask;

    /** The second element depends on the type of thing being kicked. Operators
     * taskIDs are stored, Endpoints the endpoint pointer is stored.
     */
    union
    {
        /** The bg int task of the operator to kick */
        BGINT_TASK op_bgint_task;
        /** The endpoint to kick */
        ENDPOINT *ep;
    }kt;
} KP_ELEMENT;

/* Internal structure used by opmgr for managing propagation of kicks between operators. */
typedef struct KPT
{
    /** Length of table array */
    unsigned table_length;
    /** Number of operators connected to source terminals */
    unsigned num_op_sources;
    /** Number of operators connected to sink terminals */
    unsigned num_op_sinks;
    /** Number of endpoints connected to source terminals */
    unsigned num_ep_sources;
    /** Number of endpoints connected to sink terminals */
    unsigned num_ep_sinks;
    /** Table of entities to kick */
    KP_ELEMENT table[];
} KP_TABLE;

struct TOUCHED_TERMINALS;

/* Standard operator data structure, with capability-specific data pointer */
/* For asm access structure offsets are defined in autogenerated
    <this_C_header_name>_asm_defs.h
 */
struct OPERATOR_DATA
{
    /** Connection ID - TODO: possibly partially redundant with client ID */
    CONNECTION_LINK con_id;

    /** operator ID */
    INT_OP_ID id;

    /** Task ID */
    taskid task_id;

    /** Creator client ID */
    CONNECTION_PEER creator_client_id;

    /** Creator processor ID */
    PROC_ID_NUM processor_id;

    /** Pointer to static capability data */
    const struct CAPABILITY_DATA *cap_data;

    /** Flag indicating running / stopped etc. state */
    OP_STATE state;

    /** Flag indicating that processing is suspended.
     * Note byte packing is both storage and code efficient */
    bool processing_suspended :8;

#if OPMGR_SYNC_KICKED_IMPLEMENTATION == OPMGR_SYNC_KICKED_BASIC
    /** Flag indicating that processing should be triggered when resumed.
     * Note byte packing is both storage and code efficient */
    bool processing_rerun_requested :8;
#endif

#ifdef INSTALL_THREAD_OFFLOAD
    /** TRUE if the operator should attempt to make use of thread offload. */
    bool thread_offload_enabled:8;
#endif

    /** Field indicating the direction in wich the kicks are ignored. */
    STOP_KICK stop_chain_kicks;

#ifdef INSTALL_EVENT_BASED_SNIFF
    /* sniffer, if available, will be invoked just before the operator task runs */
    bool enable_pre_run_sniff:8;

    /* sniffer, if available,  will be invoked immediately after the operator task finished */
    bool enable_post_run_sniff:8;
#endif

    /** Table caching operators & endpoints that may need to recieve a kick
     * after this operator has run.
     */
    KP_TABLE *kick_propagation_table;

#ifdef PROFILER_ON
    /**
     * Pointer to the profiler of the operator. This will measure the MIPS
     * usage of the process_data function of the operator.
     */
    profiler *profiler;
#endif

    /** Pointer to a next operator in a list, e.g. kept my OpMgr */
    struct OPERATOR_DATA* next;
    /** to save a few instructions and a memory read in redirection */
    void (*local_process_data)(struct OPERATOR_DATA*, struct TOUCHED_TERMINALS*);

    /** Pointer for sub-classing a capability*/
    void *cap_class_ext;

    /** Linked list of sink terminals */
    ENDPOINT* sink_terminals;

    /** Linked list of source terminals */
    ENDPOINT* source_terminals;

    /**
     * Unused field. On Maor 2.0 and later chips the intention is for
     * this field to specify at operator creation where the big capability
     * allocations are done: normal heap or extra power saving heap.
     */
    unsigned heap_preference;

    /** Some extra data needed by specific instance */
    void* extra_op_data;
};

#endif  /* OPMGR_OPERATOR_DATA_H */

